package com.ts.file;

import com.ts.comm.SysString;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by yingzi on 2017-3-22.
 */
public class SysFile {

    /**
     * 把指定的内容写到指定路径的文本文件上
     *
     * @param path     指定路径
     * @param context  要写的内容
     * @param sCharset 字符串编码，支持中文写入
     * @throws Exception
     * @throws Exception 操作文件时发生的异常
     */
    public static void writeFile(String path, String context, boolean isAppend, String sCharset) throws Exception {
        // 从控制台输入内容写入文件

        if (!SysString.isEmpty(path)) {
            int ix = 0;
            // 替换\ 或/
            if (path.lastIndexOf("\\") != -1) {
                ix = path.lastIndexOf("\\");
            } else {
                ix = path.lastIndexOf("/");
            }
            String relpath = path.substring(0, ix);
            File fl = new File(relpath);
            if (!fl.exists()) {
                fl.createNewFile();
            }
            try {
                FileOutputStream o = new FileOutputStream(path, isAppend);
                o.write(context.getBytes(sCharset));
                o.close();
            } catch (Exception e) {
                throw e;
            }
        }
    }

    /**
     * 创建文件夹,(存在不删除)
     *
     * @param path 存储文件夹路径
     * @throws Exception
     */
    public static boolean createDir(String path) throws Exception {
        boolean result = false;
        try {
            File dir = new File(path);
            if (!dir.exists()) {
                dir.mkdirs();
                result = true;
            } else {
                result = true;
            }
        } catch (Exception e) {
            throw e;
        }

        return result;
    }

    /**
     * 创建文件,(存在不删除)
     *
     * @param filename 文件名称
     * @throws Exception
     * @ param path  存储文件路径
     */
    public static boolean createFile(String path, String filename) throws Exception {
        boolean result = false;
        File file = new File(path + "/" + filename);

        try {
            if (createDir(path)) {
                if (!file.exists()) {
                    file.createNewFile();
                    result = true;
                } else {
                    result = true;
                }
            }
        } catch (IOException e) {
            throw e;
        }
        return result;
    }

    /**
     * 删除单个文件
     *
     * @param sPath 被删除文件的路径+文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String sPath) {
        Boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     * 删除目录（文件夹）以及目录下的文件
     *
     * @param sPath 被删除目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDir(String sPath) {
        // 如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        // 如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        Boolean flag = true;
        // 删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag)
                    break;
            } // 删除子目录
            else {
                flag = deleteDir(files[i].getAbsolutePath());
                if (!flag)
                    break;
            }
        }
        if (!flag)
            return false;
        // 删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 把一个指定的二进制文件拷贝到指定的路径下
     *
     * @param fromFilePath 要拷贝哪个路径下的文件
     * @param toFilePath   拷到那个路径下
     * @throws Exception
     */
    public static void copyFile(String fromFilePath, String toFilePath) throws Exception {
        FileInputStream fis = null;
        DataInputStream dis = null;
        FileOutputStream fos = null;
        DataOutputStream dos = null;
        try {
            File readPath = new File(fromFilePath);
            File writePath = new File(toFilePath);
            fis = new FileInputStream(readPath);
            dis = new DataInputStream(fis);
            fos = new FileOutputStream(writePath, true);
            dos = new DataOutputStream(fos);
            byte[] b = new byte[2048]; // 创建 一个小车，没回读写这么多个字节。
            int i = dis.read(b); // 创建一个文件指针，判断现在已经读到什么地方。
            while (i != -1) {
                dos.write(b, 0, i); // 把b中内容从0开始，写i的长度，写到dos装饰的低级流中，此例，写到文件中。
                i = dis.read(b);
            }
            dos.flush();
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
                if (dos != null) {
                    dos.close();
                }
                if (fis != null) {
                    fis.close();
                }
                if (dis != null) {
                    dis.close();
                }
            } catch (Exception e) {

            }
        }
        long end = System.currentTimeMillis();
    }

    /**
     * 方法说明：文件加密解密（包含文件名的路径）
     *
     * @param sPath
     * @throws Exception
     * @throw
     */
    public static boolean encryeFile(String sPath) throws Exception {
        boolean isSucess = false;
        RandomAccessFile raFile = null;
        try {
            raFile = new RandomAccessFile(sPath, "rw");

            byte[] bytes = new byte[1024];

            long lPointer = raFile.getFilePointer();
            int iByteLen = raFile.read(bytes);
            while (iByteLen != -1) {
                for (int i = 0; i < iByteLen; i++) {
                    bytes[i] ^= 15;
                }
                raFile.seek(lPointer);
                raFile.write(bytes, 0, iByteLen);
                lPointer = raFile.getFilePointer();
                iByteLen = raFile.read(bytes);
            }
            isSucess = true;
        } catch (Exception e) {
            throw e;
        } finally {
            raFile.close();
        }
        return isSucess;
    }

    /**
     * 方法说明：流写入文件
     *
     * @param is    二进制流
     * @param sPath 目标文件路径
     * @return
     * @throws Exception
     * @throw
     */
    public static boolean writeBinary(InputStream is, String sPath)
            throws Exception {
        boolean flag = false;
        DataInputStream di = null;
        FileOutputStream fos = null;
        try {
            di = new DataInputStream(is);
            fos = new FileOutputStream(sPath, true);
            byte[] b = new byte[2048]; // 创建 一个小车，没回读写这么多个字节。
            int i = di.read(b);
            while (i != -1) {
                fos.write(b, 0, i);
                i = di.read(b);
            }
            fos.flush();
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
                di.close();
            } catch (Exception e) {
            }
        }
        return flag;
    }

    /**
     * 文件转换成byte[]
     *
     * @param sPath
     * @return
     * @throws Exception
     */
    public static byte[] file2Byte(String sPath) throws Exception {
        FileInputStream fis = null;
        ByteArrayOutputStream bos = null;

        try {
            File fl = new File(sPath);
            if (!fl.exists()) {
                throw new Exception("文件不存在！");
            }
            fis = new FileInputStream(fl);
            bos = new ByteArrayOutputStream();
            byte[] b = new byte[2048];
            int i = -1;
            while ((i = fis.read(b)) != -1) {
                bos.write(b, 0, i);
            }
            return bos.toByteArray();
        } catch (Exception e) {
            throw e;
        } finally {
            if (bos != null)
                bos.close();
            if (fis != null)
                fis.close();
        }
    }

    /**
     * 二进制流 转换为字节数组
     *
     * @param is 二进制流
     * @return
     * @throws Exception
     */
    public static byte[] inputSteam2Byte(InputStream is) throws Exception {
        ByteArrayOutputStream bos = null;

        try {
            bos = new ByteArrayOutputStream();

            byte[] b = new byte[2048];
            int i = -1;
            while ((i = is.read(b)) != -1) {
                bos.write(b, 0, i);
            }
            return bos.toByteArray();
        } catch (Exception e) {
            throw e;
        } finally {
            if (bos != null)
                bos.close();
        }
    }

    /**
     * 递归遍历目录以及子目录中的所有文件
     *
     * @param file       当前遍历文件
     * @param fileFilter 文件过滤规则对象，选择要保留的文件
     */
    public static List<File> loopFiles(File file, FileFilter fileFilter) {
        List<File> fileList = new ArrayList<File>();
        if (file == null) {
            return fileList;
        } else if (file.exists() == false) {
            return fileList;
        }

        if (file.isDirectory()) {
            for (File tmp : file.listFiles()) {
                fileList.addAll(loopFiles(tmp, fileFilter));
            }
        } else {
            if (null == fileFilter || fileFilter.accept(file)) {
                fileList.add(file);
            }
        }

        return fileList;
    }

}
